#include "stm32f10x.h"
#include "byte_queue.h"
#include <stdio.h>
#include "typedef.h"

#define USARTx USART2



static void initUart(void) {
  GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;  //定义串口初始化结构体
  NVIC_InitTypeDef NVIC_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;	              
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure); 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  USART_InitStructure.USART_BaudRate = 115200; //波特率
  USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位8位
  USART_InitStructure.USART_StopBits = USART_StopBits_1;	//停止位1位
  USART_InitStructure.USART_Parity = USART_Parity_No;		//校验位 无
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无流控制
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;		//使能接收和发送引脚

  USART_Init(USARTx, &USART_InitStructure); 
  USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);

  // 配置 NVIC 以使能 USARTx 中断
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);  
  
  USART_Cmd(USARTx, ENABLE);
}

//串口收发缓冲区
static uint8 tx_buf[256];
static sByteQueue tx_queue;
static uint8 rx_buf[256];
static sByteQueue rx_queue;
//串口缓冲区初始化
static void initQueue(void) {
  //初始化这两个队列
  ByteQueue_init(&tx_queue, tx_buf, 256);
  ByteQueue_init(&rx_queue, rx_buf, 256);
}
//每当收到1Byte数据，就放入rx队列
static void recvByte() {
  uint8 data = USART_ReceiveData(USARTx);
  ByteQueue_enqueue(&rx_queue, data);
}

/// @brief 从串口接收缓冲中取出1Byte数据，如果没有数据，返回-1
/// @return 按顺序取出串口接收到的数据，如果没有数据，返回-1
int16 Uart2_recvByte(void) {
  uint16 rev; 
  __disable_irq();
  rev = ByteQueue_dequeue(&rx_queue);
  __enable_irq();
  return rev;
}
/// @brief 从串口2发送1Byte数据
/// @param data 将要发送的数据
/// @return 如果串口队列已满，返回-1，否则返回0
int8 Uart2_sendByte(uint8 data) {
  int8 rev;
  __disable_irq();
  rev = ByteQueue_enqueue(&tx_queue, data);
  __enable_irq();
  USART_ITConfig(USARTx, USART_IT_TXE, ENABLE);
  return rev;
}
/// @brief 初始化串口
void Uart2_init(void) {
  initUart();
  initQueue();
}

/// @brief 串口2中断处理函数
void USART2_IRQHandler(void) {
  if (USART_GetITStatus(USARTx, USART_IT_RXNE)) {
    recvByte();
  }
  if (USART_GetITStatus(USARTx, USART_IT_TXE)) {//TX buff空中断
    int16 data = ByteQueue_dequeue(&tx_queue);//从缓冲区取出数据
    if (data >= 0) {//如果成功取出数据，则发送数据
      USART_SendData(USARTx, (unsigned char)data);
    } else {//如果发送缓冲区为空，关闭TXE中断
      USART_ITConfig(USARTx, USART_IT_TXE, DISABLE);
    }
  }
}



